/**
 * 
 */
package com.module.hq.ui.mono.heroviewer.widgets;

import java.awt.Dimension;

import com.dalonedrau.jogl.engine.GameApplet;
import com.dalonedrau.jogl.engine.JOGLErrorHandler;
import com.dalonedrau.jogl.engine.Render;
import com.dalonedrau.jogl.opengl.sprite.BasicSpriteObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteBase;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObjectFactory;
import com.dalonedrau.jogl.opengl.ui.GuiComponentImpl;
import com.dalonedrau.jogl.opengl.ui.GuiComponentLibrary;
import com.dalonedrau.jogl.opengl.ui.GuiTextItemImpl;
import com.dalonedrau.vectors.Vector3;

/**
 * Displays a statistic as a variable size stat bar.
 * @author DaLoneDrau
 */
public final class StatBar extends GuiTextItemImpl {
	/** the current value this stat bar represents. */
	private float		current;
	/** the component's id. */
	private int			id;
	/** the left sprite. */
	private SpriteBase	left;
	/** the maximum value the stat bar represents. */
	private float		max;
	/** the middle sprite - end cap. */
	private SpriteBase	middleCap;
	/** the middle sprite - empty. */
	private SpriteBase	middleEmpty;
	/** the middle sprite - full. */
	private SpriteBase	middleFull;
	/** the <code>StatBar</code>'s preferred size. */
	private Dimension	preferredSize	= new Dimension(0, 0);
	/** the right sprite. */
	private SpriteBase	right;
	/**
	 * Creates a new instance of {@link StatBar}.
	 * @param newCurrent the current value this stat bar represents
	 * @param newMax the maximum value the stat bar represents
	 * @param width the stat bar's full width
	 * @param height the stat bar's full height
	 */
	public StatBar(final float newCurrent, final float newMax, final int width,
			final int height) {
		super(null, null);
		super.setInsets(0, 0, 0, 0);
		try {
			id = GuiComponentLibrary.getInstance().getNextId();
			setPreferredSize(width, height);
			setMax(newMax);
			setCurrent(newCurrent);
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
		GuiComponentLibrary.getInstance().addComponent(this);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getId() {
		return id;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Dimension getPreferredSize() {
		return preferredSize;
	}
	/** Positions all sprites for the stat bar. */
	private void positionSprites() {
		if (super.getPosition() != null) {
			// set left position
			left.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ()
					);
			left.clearFloatStore();
			// set middle-full position
			middleFull.setPosition(
					super.getPosition().getX() + left.getWidth(),
					super.getPosition().getY(),
					super.getPosition().getZ()
					);
			middleFull.clearFloatStore();
			// set middle-cap position
			middleCap.setPosition(
					super.getPosition().getX()
							+ left.getWidth()
							+ middleFull.getWidth(),
							super.getPosition().getY(),
							super.getPosition().getZ()
					);
			middleCap.clearFloatStore();
			// set middle-empty position
			middleEmpty.setPosition(
					super.getPosition().getX()
							+ left.getWidth()
							+ middleFull.getWidth()
							+ middleCap.getWidth(),
							super.getPosition().getY(),
							super.getPosition().getZ()
					);
			middleEmpty.clearFloatStore();
			// set right position
			right.setPosition(
					super.getPosition().getX()
							+ left.getWidth()
							+ middleFull.getWidth()
							+ middleCap.getWidth()
							+ middleEmpty.getWidth(),
							super.getPosition().getY(),
							super.getPosition().getZ()
					);
			right.clearFloatStore();
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareForRendering() throws Exception {
		Render.getInstance().registerEntity(left);
		Render.getInstance().registerEntity(middleFull);
		Render.getInstance().registerEntity(middleCap);
		Render.getInstance().registerEntity(middleEmpty);
		Render.getInstance().registerEntity(right);
	}
	/** Resets the length of the stat bar after an update. */
	private void resetBarLength() {
		// a unit is the length in pixels that 1 unit of the statistic will
		// measure. if the stat bar can be 60px wide, and the max value is 10,
		// then each stat unit will be 6px wide
		float unit = preferredSize.width - left.getWidth() - right.getWidth();
		if (max <= 0f) {
			unit = 0;
		} else {
			unit /= max;
		}
		if (current == 0) {
			middleFull.setWidth(0);
			middleCap.setWidth(0);
			middleEmpty.setWidth(preferredSize.width
					- left.getWidth() - right.getWidth());
		} else {
			try {
				middleCap.setWidth(
						SpriteImageObjectFactory.getInstance().getImageById(
								middleCap.getImageRefId()).getWidth());
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
			// set the length of the middle-full sprite
			float mfLen = current * unit;
			// subtract the length of the cap
			mfLen -= middleCap.getWidth();
			middleFull.setWidth((int) mfLen);
			// set the length of the empty section
			float meLen =
					preferredSize.width - left.getWidth() - right.getWidth();
			meLen -= middleFull.getWidth();
			meLen -= middleCap.getWidth();
			middleEmpty.setWidth((int) meLen);
		}
		// re-position sprites
		positionSprites();
	}
	/**
	 * Sets the current value the stat bar represents.
	 * @param newCurrent the value to set
	 */
	public void setCurrent(final float newCurrent) {
		current = newCurrent;
		resetBarLength();
	}
	/**
	 * Sets the maximum value the stat bar represents.
	 * @param newMax the max to set
	 */
	public void setMax(final float newMax) {
		max = newMax;
		resetBarLength();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPosition(final double x, final double y, final double z) {
		super.setPosition(x, y, z);
		positionSprites();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPreferredSize(final int width, final int height) {
		preferredSize.setSize(width, height);
		try {
			if (left == null) {
				// LEFT
				SpriteImageObject img =
						SpriteImageObjectFactory.getInstance().getImageByName(
								"hq_mono_stat_bar_left");
				left = new BasicSpriteObject();
				left.setImageRefId(img.getRefId());
				left.setWidth(img.getWidth());
				left.setHeight(img.getHeight());

				// RIGHT
				img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_mono_stat_bar_right");
				right = new BasicSpriteObject();
				right.setImageRefId(img.getRefId());
				right.setWidth(img.getWidth());
				right.setHeight(img.getHeight());

				// MIDDLE - CAP
				img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_mono_stat_bar_middle_cap");
				middleCap = new BasicSpriteObject();
				middleCap.setImageRefId(img.getRefId());
				middleCap.setHeight(img.getHeight());

				int middle = width;
				middle -= left.getWidth();
				middle -= right.getWidth();
				middle -= middleCap.getWidth();

				// MIDDLE - FULL
				img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_mono_stat_bar_middle_full");
				middleFull = new BasicSpriteObject();
				middleFull.setImageRefId(img.getRefId());
				middleFull.setHeight(img.getHeight());

				// MIDDLE - EMPTY
				img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_mono_stat_bar_middle_empty");
				middleEmpty = new BasicSpriteObject();
				middleEmpty.setImageRefId(img.getRefId());
				middleEmpty.setHeight(img.getHeight());

				img = null;
			}
			resetBarLength();
			// set left position
			left.setPosition(new Vector3(0, 0, 0));
			// set middle-full position
			middleFull.setPosition(new Vector3(left.getWidth(), 0, 0));
			// set middle-cap position
			middleCap.setPosition(new Vector3(
					left.getWidth() + middleFull.getWidth(), 0, 0));
			// set middle-empty position
			middleEmpty.setPosition(new Vector3(
					left.getWidth()
							+ middleFull.getWidth()
							+ middleCap.getWidth(), 0, 0));
			// set right position
			right.setPosition(new Vector3(
					width - right.getWidth(), 0, 0));

			positionSprites();
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
}
